package site.edody.dframe.plugin;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.matcher.ElementMatchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.tools.*;
import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通用动态Java代码编译器
 * 提供源码编译和字节码生成两种方式，完全通用不依赖特定场景
 */
public class DynamicJavaCompiler {

    // 添加类缓存
    private final Map<String, Class<?>> generatedClassCache = new ConcurrentHashMap<>();

    private final CodeBasedDependencyManager dependencyManager;
    private final JavaCompiler compiler;
    private final JavaFileManager fileManager;
    private final List<SimpleJavaFileObject> compilationUnits;
    private final Map<String, byte[]> compiledClasses;

    private static final Logger log = LoggerFactory.getLogger(DynamicJavaCompiler.class);

    public DynamicJavaCompiler(CodeBasedDependencyManager dependencyManager) {
        this.dependencyManager = dependencyManager;
        this.compiler = ToolProvider.getSystemJavaCompiler();
        this.compilationUnits = new ArrayList<>();
        this.compiledClasses = new HashMap<>();

        if (compiler == null) {
            throw new RuntimeException("无法获取Java编译器，请确保在JDK环境中运行");
        }

        StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
        this.fileManager = new CustomJavaFileManager(standardFileManager);

        log.info("DynamicJavaCompiler 初始化完成");
    }

    /**
     * 编译Java源代码为Class对象
     */
    public Class<?> compileSource(String className, String sourceCode) throws CompilationException {
        return compileSource(className, sourceCode, Collections.emptyList());
    }

    /**
     * 编译Java源代码为Class对象（带自定义编译选项）
     */
    public Class<?> compileSource(String className, String sourceCode, List<String> additionalOptions) throws CompilationException {
        try {
            // 创建内存中的Java文件对象
            SimpleJavaFileObject sourceFile = new StringJavaFileObject(className, sourceCode);
            compilationUnits.add(sourceFile);

            // 设置编译选项
            List<String> options = new ArrayList<>();
            options.add("-classpath");
            options.add(getClassPath());
            options.add("-parameters"); // 保留参数名信息
            options.add("-proc:none");  // 禁用批注处理
            options.add("-Xlint:-options"); // 隐藏选项警告
            options.addAll(additionalOptions);

            // 执行编译
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
            JavaCompiler.CompilationTask task = compiler.getTask(
                    null, fileManager, diagnostics, options, null, compilationUnits
            );

            boolean success = task.call();

            // 检查编译结果
            if (!success) {
                StringBuilder errorMsg = new StringBuilder();
                errorMsg.append("编译失败:\n");
                for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                    errorMsg.append(String.format("行 %d, 列 %d: %s\n",
                            diagnostic.getLineNumber(),
                            diagnostic.getColumnNumber(),
                            diagnostic.getMessage(Locale.getDefault())));
                }
                throw new CompilationException(errorMsg.toString());
            }

            // 从内存中加载编译后的类
            if (compiledClasses.containsKey(className)) {
                byte[] bytecode = compiledClasses.get(className);
                return loadClassFromBytes(className, bytecode);
            } else {
                throw new CompilationException("编译成功但未找到生成的类: " + className);
            }

        } finally {
            compilationUnits.clear();
        }
    }

    /**
     * 使用Byte Buddy动态生成接口实现类
     */
    public Class<?> generateInterfaceImplementation(String className, String interfaceName,
                                                    Map<String, Object> methodImplementations)
            throws ClassNotFoundException, GenerationException {
        try {
            // 加载目标接口
            Class<?> interfaceClass = dependencyManager.loadClass(interfaceName);

            DynamicType.Builder<?> builder = new ByteBuddy()
                    .subclass(Object.class)
                    .name(className)
                    .implement(interfaceClass);

            // 为接口中的每个方法添加实现
            for (Method method : interfaceClass.getMethods()) {
                String methodName = method.getName();
                Object implementation = methodImplementations.get(methodName);

                if (implementation != null) {
                    builder = builder.method(ElementMatchers.named(methodName))
                            .intercept(MethodDelegation.to(implementation));
                } else {
                    // 如果没有提供实现，使用默认实现（抛出异常）
                    builder = builder.method(ElementMatchers.named(methodName))
                            .intercept(MethodDelegation.to(new DefaultMethodInterceptor()));
                }
            }

            // 生成类并加载
            DynamicType.Unloaded<?> unloadedType = builder.make();
            return unloadedType.load(
                    dependencyManager.getClassLoader(),
                    ClassLoadingStrategy.Default.WRAPPER
            ).getLoaded();

        } catch (Exception e) {
            throw new GenerationException("动态生成接口实现类失败: " + className, e);
        }
    }

    /**
     * 使用Byte Buddy动态生成子类
     */
    public Class<?> generateSubclass(String className, String superClassName,
                                     Map<String, Object> methodImplementations) throws ClassNotFoundException, GenerationException {
        try {
            // 加载父类
            Class<?> superClass = dependencyManager.loadClass(superClassName);

            DynamicType.Builder<?> builder = new ByteBuddy()
                    .subclass(superClass)
                    .name(className);

            // 为每个方法添加实现
            for (Map.Entry<String, Object> entry : methodImplementations.entrySet()) {
                String methodName = entry.getKey();
                Object implementation = entry.getValue();

                builder = builder.method(ElementMatchers.named(methodName))
                        .intercept(MethodDelegation.to(implementation));
            }

            // 生成类并加载
            DynamicType.Unloaded<?> unloadedType = builder.make();
            return unloadedType.load(
                    dependencyManager.getClassLoader(),
                    ClassLoadingStrategy.Default.WRAPPER
            ).getLoaded();

        } catch (Exception e) {
            throw new GenerationException("动态生成子类失败: " + className, e);
        }
    }

    /**
     * 使用Byte Buddy动态生成简单类（无父类或接口）
     */
    public Class<?> generateSimpleClass(String className, Map<String, Object> methodImplementations)
            throws GenerationException {
        try {
            DynamicType.Builder<?> builder = new ByteBuddy()
                    .subclass(Object.class)
                    .name(className);

            // 为每个方法添加实现
            for (Map.Entry<String, Object> entry : methodImplementations.entrySet()) {
                String methodName = entry.getKey();
                Object implementation = entry.getValue();

                builder = builder.defineMethod(methodName, Object.class, Modifier.PUBLIC)
                        .withParameters(Object[].class)
                        .intercept(MethodDelegation.to(implementation));
            }

            // 生成类并加载
            DynamicType.Unloaded<?> unloadedType = builder.make();
            return unloadedType.load(
                    dependencyManager.getClassLoader(),
                    ClassLoadingStrategy.Default.WRAPPER
            ).getLoaded();

        } catch (Exception e) {
            throw new GenerationException("动态生成简单类失败: " + className, e);
        }
    }

    /**
     * 从字节数组加载类
     */
    private Class<?> loadClassFromBytes(String className, byte[] bytecode) {
        try {
            // 使用依赖管理器的类加载器来加载类
            Method defineClassMethod = ClassLoader.class.getDeclaredMethod(
                    "defineClass", String.class, byte[].class, int.class, int.class
            );
            defineClassMethod.setAccessible(true);

            return (Class<?>) defineClassMethod.invoke(
                    dependencyManager.getClassLoader(),
                    className, bytecode, 0, bytecode.length
            );
        } catch (Exception e) {
            throw new RuntimeException("加载编译后的类失败: " + className, e);
        }
    }

    /**
     * 获取完整的类路径
     */
    private String getClassPath() {
        try {
            StringBuilder classPathBuilder = new StringBuilder();

            // 1. 添加系统类路径
            String systemClassPath = System.getProperty("java.class.path");
            classPathBuilder.append(systemClassPath);

            // 2. 添加依赖管理器的类路径
            ClassLoader classLoader = dependencyManager.getClassLoader();
            if (classLoader instanceof URLClassLoader) {
                URLClassLoader urlClassLoader = (URLClassLoader) classLoader;

                for (URL url : urlClassLoader.getURLs()) {
                    if (url.getProtocol().equals("file")) {
                        classPathBuilder.append(File.pathSeparator).append(url.getFile());
                    }
                }
            }

            String fullClassPath = classPathBuilder.toString();
            log.debug("编译类路径长度: {}", fullClassPath.length());
            return fullClassPath;

        } catch (Exception e) {
            log.warn("获取类路径失败，使用系统默认类路径", e);
            return System.getProperty("java.class.path");
        }
    }

    // 内部类保持不变...
    private static class StringJavaFileObject extends SimpleJavaFileObject {
        private final String sourceCode;

        protected StringJavaFileObject(String className, String sourceCode) {
            super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.sourceCode = sourceCode;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return sourceCode;
        }
    }

    private class CustomJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {
        protected CustomJavaFileManager(JavaFileManager fileManager) {
            super(fileManager);
        }

        @Override
        public JavaFileObject getJavaFileForOutput(Location location, String className,
                                                   JavaFileObject.Kind kind, FileObject sibling) {
            return new SimpleJavaFileObject(URI.create("string:///" + className.replace('.', '/') + kind.extension), kind) {
                @Override
                public OutputStream openOutputStream() {
                    return new ByteArrayOutputStream() {
                        @Override
                        public void close() throws IOException {
                            super.close();
                            compiledClasses.put(className, toByteArray());
                        }
                    };
                }
            };
        }
    }

    public static class DynamicMethodInterceptor {
        private final String implementationCode;

        public DynamicMethodInterceptor(String implementationCode) {
            this.implementationCode = implementationCode;
        }

        @RuntimeType
        public Object intercept(@AllArguments Object[] args, @Origin Method method) {
            log.info("执行方法: {}, 实现代码: {}", method.getName(), implementationCode);
            return implementationCode;
        }
    }

    public static class DefaultMethodInterceptor {
        @RuntimeType
        public Object intercept(@SuperCall Callable<?> superCall, @Origin Method method) throws Exception {
            throw new UnsupportedOperationException("方法 " + method.getName() + " 未实现");
        }
    }

    public static class CompilationException extends Exception {
        public CompilationException(String message) {
            super(message);
        }

        public CompilationException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    public static class GenerationException extends Exception {
        public GenerationException(String message) {
            super(message);
        }

        public GenerationException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    /**
     * 使用字符串方法实现生成接口实现类
     */
    public Class<?> generateInterfaceImplementationWithStrings(String className, String interfaceName,
                                                               Map<String, String> methodImplementations)
            throws ClassNotFoundException, GenerationException {
        try {
            // 加载目标接口
            Class<?> interfaceClass = dependencyManager.loadClass(interfaceName);

            if (!interfaceClass.isInterface()) {
                throw new GenerationException(interfaceName + " 不是接口，请使用 generateClass 方法");
            }

            return generateClass(className, interfaceName, methodImplementations);

        } catch (Exception e) {
            throw new GenerationException("动态生成接口实现类失败: " + className, e);
        }
    }

    /**
     * 使用字符串方法实现生成子类
     */
    public Class<?> generateSubclassWithStrings(String className, String superClassName,
                                                Map<String, String> methodImplementations)
            throws ClassNotFoundException, GenerationException {
        try {
            // 加载父类
            Class<?> superClass = dependencyManager.loadClass(superClassName);

            if (superClass.isInterface()) {
                throw new GenerationException(superClassName + " 是接口，请使用 generateInterfaceImplementationWithStrings 方法");
            }

            return generateClass(className, superClassName, methodImplementations);

        } catch (Exception e) {
            throw new GenerationException("动态生成子类失败: " + className, e);
        }
    }

    /**
     * 智能生成类 - 自动判断是接口还是类，并缓存结果
     */
    public Class<?> generateClass(String className, String targetName,
                                  Map<String, String> methodImplementations)
            throws ClassNotFoundException, GenerationException {

        // 使用包含类加载器信息的缓存键
        ClassLoader currentClassLoader = dependencyManager.getClassLoader();
        String classLoaderId = Integer.toHexString(System.identityHashCode(currentClassLoader));
        String cacheKey = className + ":" + targetName + ":" + classLoaderId;

        log.debug("生成缓存键: {}, 类加载器: {}", cacheKey, currentClassLoader);

        // 检查缓存，但验证类的有效性
        if (generatedClassCache.containsKey(cacheKey)) {
            Class<?> cachedClass = generatedClassCache.get(cacheKey);
            log.debug("从缓存获取已生成的类: {}", className);

            // 验证缓存的类是否仍然有效
            if (isClassValid(cachedClass, targetName)) {
                return cachedClass;
            } else {
                log.debug("缓存的类已失效，重新生成: {}", className);
                generatedClassCache.remove(cacheKey);
            }
        }

        try {
            // 加载目标类或接口
            Class<?> targetClass = dependencyManager.loadClass(targetName);
            log.debug("成功加载目标类: {}", targetName);

            // 创建字符串执行器
            StringMethodExecutor executor = new StringMethodExecutor(methodImplementations, dependencyManager);

            DynamicType.Builder<?> builder;

            if (targetClass.isInterface()) {
                // 如果是接口，实现它
                builder = new ByteBuddy()
                        .subclass(Object.class)
                        .name(className)
                        .implement(targetClass);
                log.debug("生成接口实现类: {} -> {}", className, targetName);
            } else {
                // 如果是类，继承它
                builder = new ByteBuddy()
                        .subclass(targetClass)
                        .name(className);
                log.debug("生成子类: {} -> {}", className, targetName);
            }

            // 为每个方法添加实现
            for (String methodName : methodImplementations.keySet()) {
                builder = builder.method(ElementMatchers.named(methodName))
                        .intercept(MethodDelegation.to(executor));
                log.debug("为方法 {} 添加实现", methodName);
            }

            // 生成类并加载
            DynamicType.Unloaded<?> unloadedType = builder.make();
            log.debug("ByteBuddy 生成类完成: {}", className);

            Class<?> generatedClass = unloadedType.load(
                    currentClassLoader,
                    ClassLoadingStrategy.Default.WRAPPER_PERSISTENT
            ).getLoaded();

            // 验证生成的类是否有效
            if (!isClassValid(generatedClass, targetName)) {
                throw new GenerationException("生成的类验证失败: " + className);
            }

            // 缓存生成的类
            generatedClassCache.put(cacheKey, generatedClass);
            log.info("成功生成并缓存类: {} -> {} (类加载器: {})", className, targetName, classLoaderId);

            return generatedClass;

        } catch (Exception e) {
            log.error("动态生成类失败: {} -> {}, 错误: {}", className, targetName, e.getMessage(), e);
            throw new GenerationException("动态生成类失败: " + className + " -> " + targetName, e);
        }
    }

    /**
     * 验证类是否有效
     */
    private boolean isClassValid(Class<?> generatedClass, String targetName) {
        try {
            // 检查类是否可以被实例化
            generatedClass.getDeclaredConstructor().newInstance();

            // 检查目标类是否仍然可以加载并且与生成的类兼容
            Class<?> currentTargetClass = dependencyManager.loadClass(targetName);

            if (currentTargetClass.isInterface()) {
                // 检查生成的类是否实现了目标接口
                for (Class<?> iface : generatedClass.getInterfaces()) {
                    if (iface.getName().equals(targetName)) {
                        return true;
                    }
                }
                return false;
            } else {
                // 检查生成的类是否继承自目标类
                return generatedClass.getSuperclass().getName().equals(targetName);
            }
        } catch (Exception e) {
            log.debug("类验证失败: {}, 原因: {}", generatedClass.getName(), e.getMessage());
            return false;
        }
    }

    /**
     * 清除特定目标类的缓存
     */
    public void clearCacheForTarget(String targetName) {
        List<String> keysToRemove = new ArrayList<>();
        for (String key : generatedClassCache.keySet()) {
            if (key.contains(":" + targetName + ":")) {
                keysToRemove.add(key);
            }
        }
        for (String key : keysToRemove) {
            generatedClassCache.remove(key);
            log.debug("清除缓存: {}", key);
        }
        log.info("已清除目标类 {} 的缓存，移除 {} 个缓存项", targetName, keysToRemove.size());
    }

    /**
     * 强制重新生成类（绕过缓存）
     */
    public Class<?> generateClassForce(String className, String targetName,
                                       Map<String, String> methodImplementations)
            throws ClassNotFoundException, GenerationException {
        clearCacheForTarget(targetName);
        return generateClass(className, targetName, methodImplementations);
    }





    /**
     * 检查类兼容性
     */
    private boolean isClassCompatible(Class<?> generatedClass, Class<?> targetClass) {
        try {
            if (targetClass.isInterface()) {
                // 检查生成的类是否实现了目标接口
                Class<?>[] interfaces = generatedClass.getInterfaces();
                for (Class<?> iface : interfaces) {
                    if (iface.equals(targetClass)) {
                        return true;
                    }
                }
            } else {
                // 检查生成的类是否继承自目标类
                return generatedClass.getSuperclass().equals(targetClass);
            }
        } catch (Exception e) {
            log.debug("类兼容性检查失败", e);
        }
        return false;
    }

    /**
     * 直接从缓存获取已生成的类
     */
    public Class<?> getGeneratedClass(String className, String targetName) {
        String cacheKey = className + ":" + targetName;
        return generatedClassCache.get(cacheKey);
    }

    /**
     * 清除类缓存
     */
    public void clearClassCache() {
        generatedClassCache.clear();
        log.info("已清除生成的类缓存");
    }

    /**
     * 检查目标类型是接口还是类
     */
    public String checkTargetType(String targetName) throws ClassNotFoundException {
        Class<?> targetClass = dependencyManager.loadClass(targetName);
        if (targetClass.isInterface()) {
            return "接口";
        } else if (java.lang.reflect.Modifier.isAbstract(targetClass.getModifiers())) {
            return "抽象类";
        } else {
            return "具体类";
        }
    }

    /**
     * 获取目标类的所有抽象方法
     */
    public List<String> getAbstractMethods(String targetName) throws ClassNotFoundException {
        Class<?> targetClass = dependencyManager.loadClass(targetName);
        List<String> abstractMethods = new ArrayList<>();

        for (Method method : targetClass.getDeclaredMethods()) {
            if (java.lang.reflect.Modifier.isAbstract(method.getModifiers())) {
                abstractMethods.add(method.getName() + method.toString());
            }
        }

        return abstractMethods;
    }
}